
public class EventStatus extends Avl<Line> {

    @Override
    public void insertAVL(Node node, Node father, boolean left, Line new_data) {
        if (node.isEmpty()) {
            node.data = new_data;
            node.left = new Node();
            node.right = new Node();
        } else {
            int diff = node.data.compareTo(new_data);
            if (diff == 0) {
                /*
                 * Rien à faire car cela signifie qu'ils sont identiques nous ne
                 * le retenons donc pas, car il ne découvrira pas d'intersection
                 * supplémentaire. On prend juste le plus grand des 2 pour ne pas
                 * perdre de possibles intersections.
                 */
                /* if(new_data.getY2() < ((Line)node.data).getY2())
                    node.data = new_data;/* Cas non géré */
            } else if (diff > 0) {
                insertAVL(node.right, node, false, new_data);
                super.equilibrate(node, father, left);
            } else if (diff < 0) {
                insertAVL(node.left, node, true, new_data);
                super.equilibrate(node, father, left);
            }
        }
    }
    
    @Override
    protected void removeAVL(Node node, Node father, boolean left, Line old_data) {
        if (!node.isEmpty()) {
            if(((Line)node.data).equals(old_data)) {
                super.removeRootAVL(node, father, left);
            } else if (node.data.compareTo(old_data) < 0) {
                super.removeAVL(node.left, node, true, old_data);
                super.equilibrate(node, father, left);
            } else if (node.data.compareTo(old_data) > 0) {
                super.removeAVL(node.right, node, false, old_data);
                super.equilibrate(node, father, left);
            }
        }
    }
    
    /*public Line[] getNeightbors(Point p) {
        Line[] results = new Line[2];
        Line tmp_line = super.getFirstNode(super.root, null, false);
        
        //Retourne null si arbre non vide, mais p avant tout segment
        if(tmp_line == null || (tmp_line != null && tmp_line.getXForY(p.getY()) > p.getX()))
            return null;
        
        while(tmp_line != null && tmp_line.getXForY(p.getY()) <= p.getX()) {
            results[0] = results[1];
            results[1] = tmp_line;

            tmp_line = super.getSuccessor(tmp_line);
        }
        
        //Retourne null si arbre visité, mais p après tout segment
        if(results[1] != null && results[1].getXForY(p.getY()) <= p.getX())
            return null;
        
        return results;
    }/**/
    
    public Line[] getNeightbors2(Point p) {
        Line line1, line2;
        line1 = getAVLPredecessorFromPoint(super.root, p);
        if(line1 == null) return null;
        line2 = getAVLSuccessorFromPoint(super.root, p);
        if(line2 == null) return null;
        return new Line[]{line1, line2};
    }
    
    public Line getAVLPredecessorFromPoint(Node node, Point data) {
        if(node.isEmpty()) return null;
        double actual_x = ((Line)node.data).getXForY(data.y);
        if(actual_x > data.x || 1E-8 > Math.abs(actual_x - data.x)) {
            if(!node.left.isEmpty())
                return getAVLPredecessorFromPoint(node.left, data);
            else
                return null;
        } else {
            if(!node.right.isEmpty()) {
                Line result = getAVLPredecessorFromPoint(node.right, data);
                if(result != null) {
                    return result;
                }
            }
            return (Line)node.data;
        }
    }
    
    public Line getAVLSuccessorFromPoint(Node node, Point data) {
        if(node.isEmpty()) return null;
        double actual_x = ((Line)node.data).getXForY(data.y);
        if(actual_x < data.x || 1E-8 > Math.abs(actual_x - data.x)) {
            if(!node.right.isEmpty())
                return getAVLSuccessorFromPoint(node.right, data);
            else
                return null;
        } else {
            if(!node.left.isEmpty()) {
                Line result = getAVLSuccessorFromPoint(node.left, data);
                if(result != null) {
                    return result;
                }
            }
            return (Line)node.data;
        }
    }
    
    public Line getLeftmostSegment(Node n, Point p, Line result) {
        if(n.isEmpty() || (result != null && !((Line)n.data).contains(p)))
            return result;
        else if(((Line)n.data).contains(p)) {
            return getLeftmostSegment(n.left, p, (Line)n.data);
        }
        else { 
           double actual_x = ((Line)n.data).getXForY(p.y);
            if(actual_x < p.x)
                return getLeftmostSegment(n.right, p, result);
            else {
                return getLeftmostSegment(n.left, p, result);
            }
        }
    }
   
    public Line getRightmostSegment(Node n, Point p, Line result) {
        if(n.isEmpty() || (result != null && !((Line)n.data).contains(p)))
            return result;
        else if(((Line)n.data).contains(p)) {
            return getRightmostSegment(n.right, p, (Line)n.data);
        }
        else {
            double actual_x = ((Line)n.data).getXForY(p.y);
            if(actual_x > p.x)
                return getRightmostSegment(n.left, p, result);
            else
                return getRightmostSegment(n.right, p, result);
        }
    }
}
